local httparg    = require("shared.api.httparg")
local response   = require("shared.api.response")
local def        = require("shared.api.def")
local config     = require("config")
local tag        = httparg.tag()
local assertion  = httparg.assertion
local util                  = require "proxy.game.common.util"
local fill_response_header  = util.fill_response_header
local is_match_content_type = util.is_match_content_type
local get_content_decoder   = util.get_content_decoder
local ngx        = _G.ngx
local ERROR_CODE = def.ERROR_CODE
local AMOUNT_SCALE = 10

local cjson = require "cjson.safe"
      cjson.encode_max_depth(32)
      cjson.decode_max_depth(32)

local bigdecimal = require("bigdecimal")
      bigdecimal.digit_separation_count(0)
      bigdecimal.digit_leader('\0')


local ARGS = {
    -- exist body?
    tag.body('json', 'required'),

    username         = tag.json.username        ('string', 'required', assertion.non_empty_string()),
    currency         = nil,  -- set it later
    coin_token       = tag.json.coin_token      ('string', 'required', assertion.non_empty_string()),
    address          = tag.json.address         ('string', 'required', assertion.non_empty_string()),
    amount           = nil,  -- set it later
    fee_coin         = tag.json.fee_coin        ('string', 'required', assertion.non_empty_string()),
    fee_amount       = tag.json.fee_amount      ('string', 'required', assertion.non_empty_string()),
    payout           = tag.json.payout          ('string', 'required', assertion.non_empty_string()),
    payment_channel  = tag.json.payment_channel ('string', 'required', assertion.non_empty_string()),
    account          = tag.json.account         ('string', 'required', assertion.non_empty_string()),
    alliance         = nil
}

-- use coin_toke to get currency
do
  ARGS.coin_token = string.upper(ARGS.coin_token)

  local currency = config.VAR.COIN_TOKEN_MAP[ARGS.coin_token]
  if not currency then
      response.error(ERROR_CODE.UNKNOWN_COIN_TOKEN)
  end
  ARGS.currency = currency
end

do
  if ARGS.fee_coin and ARGS.fee_coin ~= ARGS.currency then
    response.error({
        message     = def.ERROR_CODE.INVALID_OPERATION,
        description = "unsupported different coin type between 'coin_token' and 'fee_coin'",
    })
  end
end

do
  local payout     = bigdecimal.new(ARGS.payout)
  local fee_amount = bigdecimal.new(ARGS.fee_amount)
  local amount     = payout - fee_amount

  ARGS.amount = bigdecimal.round(amount, AMOUNT_SCALE):tostring('F')
end

-- set alliance
do
  ARGS.alliance = "muse"
end



local RESULT = {}
local dataapi                = require("shared.api.dataapi")
local payment_api            = require("shared.api.paymentgatewayapi")
local payment_channel_helper = require("shared.api.payment-channel-helper")
local uuidObj = require 'resty.jit-uuid'
      uuidObj.seed(os.time())

local headers  = ngx.req.get_headers()
do
  headers['X-Forwarded-For'] = ngx.var.proxy_add_x_forwarded_for
  for k,v in pairs(headers) do
    local low_header = string.lower(k)
    if low_header == "x-http-method-override" or
       low_header == "accept-encoding" then
      headers[k] = nil
    end
  end
end



--===================新用户引导-提现限制=======================================================
do
  local dataapi   = require("shared.api.dataapi")
  local reply, err = dataapi.activity_reward_withdraw_conditions.peek(
    {
      account      = ARGS.account,
      reward_type  = "REGISTER_USER_GUIDANCE",
    })

  if err then
    if err["message"] ~= "NO_CONTENT" then
      response.error(err)
    end
  end

  -- export  conditions_met  withdraw_min_round
  if reply and reply["withdraw_conditions_met"] and reply["withdraw_conditions_met"] == "0" then
    local replyTotal, errTotal = dataapi.activity_reward_withdraw_conditions.round_total(
      {
        account   = ARGS.account,
      })
    if errTotal and errTotal["message"] ~= "NO_CONTENT" then
        response.error(errTotal)
    end

    local bet_total        = replyTotal["bet_total"] or 0
    local withdrawMinRound = tonumber(reply["withdraw_min_round"]) or 0
    if withdrawMinRound > 0 then
      if bet_total > 0 and bet_total >= withdrawMinRound then
        dataapi.activity_reward_withdraw_conditions.met(
          {
            account   = ARGS.account,
            id        = reply["id"]
          })
      else
        local errMap = {
          ["message"]="USER_GUIDANCE_WITHDRAW_CONDITIONS_NOT_MET",
          ["description"]="",
        }
        response.error(errMap)
      end
    end
  end
end
--===================新用户引导-提现限制=======================================================



--///////注册送U活动提现限制//////////////////////////////////////////////////////////////////////////////////////////////////////////////
do
  local reply, err = dataapi.activity_register_reward.peek(
    {
      account = ARGS.account,
    })

  if err then
    if err["message"] ~= "NO_CONTENT" then
      response.error(err)
    end
  end

  -- export  conditions_met  withdraw_min_round
  if reply and reply["conditions_met"] and reply["conditions_met"] == "0" then
    local replyTotal, errTotal = dataapi.activity_register_reward.round_total(
      {
        account = ARGS.account,
      })
    if errTotal and errTotal["message"] ~= "NO_CONTENT" then
        response.error(errTotal)
    end

    local bet_total        = replyTotal["bet_total"] or 0
    local withdrawMinRound = 4500 --tonumber(reply["withdraw_min_round"]) or 4500
    if bet_total >= withdrawMinRound then
      dataapi.activity_register_reward.met(
        {
          account = ARGS.account,
        })
    else
      local errMap = {
        ["message"]="CONDITIONS_NOT_MET",
        ["description"]="You participated in the activity of registering to send USDT,Cash withdrawal can be made at any time when the bet amount meets 4500 USDT",
      }
      response.error(errMap)
    end
  end
end
--/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

-- get payment_channel
local PAYMENT_CHANNEL = ARGS.payment_channel

-- create withdrawal_slip id
local WITHDRAWAL_ID
do
  local reply, err = dataapi.withdrawal_slip.create(
    {
      username               = ARGS.username,
      account                = ARGS.account,
      amount                 = ARGS.amount,
      beneficiary_address    = ARGS.address,
      payment_channel        = PAYMENT_CHANNEL,
      coin                   = ARGS.currency,
      coin_token             = ARGS.coin_token,
      remark                 = nil,
      operation_idempotence  = uuidObj(),
      fee_amount             = ARGS.fee_amount,
      payout                 = ARGS.payout,
      create_at              = ngx.time()
    })

  if err then
    response.error(err)
  end

  -- export
  WITHDRAWAL_ID = reply.id
end

-- place withdrawal_slip
do
  -- split address and memo
  local beneficiary_address, memo = string.match(ARGS.address, "^([^|]+)|?(.*)$")
  if memo == "" then
      memo = nil
  end

  -- set withdraw_amount
  local WITHDRAW_AMOUNT = ARGS.amount
  if PAYMENT_CHANNEL == "muse" then
    WITHDRAW_AMOUNT = ARGS.payout
  end


  local place_withdrawal_slip_reply, slipErr = payment_api.place_withdrawal_slip(
    headers,
    PAYMENT_CHANNEL,
    {
      coin_token = ARGS.coin_token,
      address    = beneficiary_address,
      request_id = WITHDRAWAL_ID,
      amount     = WITHDRAW_AMOUNT,
      username   = ARGS.username,
      account    = ARGS.account,
      alliance   = ARGS.alliance,
      memo       = memo,    --交易memo (在某些幣種里面也叫tag)，當提領幣別為 EOS, XRP, IOST 等時，視情況帶入。
    })


  -- FIXME this is not working
  if slipErr then
    if slipErr.message == "MISSING_TRANSACTION"  or
       slipErr.message == "INSUFFICIENT_BALANCE" or
       slipErr.message == "DUPLICATE_REQUEST_ID" or
       slipErr.message == "INVALID_ADDRESS" then

       if slipErr.message then
           ngx.status         = ngx.HTTP_BAD_REQUEST
           RESULT.message     = slipErr.message
           RESULT.description = ""
       end

      -- cancel withdrawal_slip
      do
        local CANCEL_IDEMPOTENCE = "CANCEL-" .. uuidObj()
        local reply, err = dataapi.withdrawal_slip.cancel(
         {
           id                    = WITHDRAWAL_ID,
           operation_idempotence = CANCEL_IDEMPOTENCE,
           payment_channel       = PAYMENT_CHANNEL,
         })

        if err then
         response.error(err)
        end
      end
    end

    response.error(slipErr)
  end

end

-- response
response.success(RESULT)

